
#include <iostream>
#include <vector>
#include "CsvLoader.h"

using namespace std;

class StringBuffer {
private:
	char* buffer;
	char* ptr;

public:
	StringBuffer(size_t size) {
		this->buffer = new char[size];
		this->ptr = this->buffer;
		this->buffer[0] = '\0';
	}

	~StringBuffer() {
		delete this->buffer;
	}

	void append(char* str) {
		char* p = str;
		while (*p != '\0') {
			*ptr = *p;
			p += 1;
			ptr += 1;
		}
		*ptr = '\0';
	}

	void append(char ch) {
		*ptr = ch;
		ptr += 1;
		*ptr = '\0';
	}

	char* to_string() {
		return this->buffer;
	}

	size_t size() {
		return this->ptr - this->buffer;
	}
};

int main(int argc, char *argv[])
{
	if (argc < 3) {
		fprintf(stderr, "Error: At least 2 arguements\n");
		return -1;
	}
	char* input_path = argv[1];
	char* output_path = argv[2];
	char* table_name = "$TABLE_NAME$";
	if (argc >= 4) {
		table_name = argv[3];
	}
	size_t limit = 1000;
	if (argc >= 5) {
		int ct = sscanf(argv[4], "%llu", &limit);
		if (ct < 1) {
			fprintf(stderr, "Error: Fourth arguement must be a number\n");
			return -1;
		}
	}

	CsvLoader &csv = *new CsvLoader(input_path);
	FILE* output = fopen(output_path, "wb");
	if (output == NULL) {
		fprintf(stderr, "Error: Cannot open file \'%s\'\n", output_path);
		return -1;
	}

	size_t size = (size_t)(csv.size() * 2.5);
	StringBuffer sql(size);

	std::vector<char*>* title = csv.read_row();
	size_t col_count = title->size();

	StringBuffer ttl(4096);
	ttl.append("INSERT INTO \"");
	ttl.append(table_name);
	ttl.append("\"(\"");

	ttl.append((*title)[0]);
	ttl.append('\"');
	for (int i = 1; i < col_count; i++) {
		ttl.append(",\"");
		ttl.append((*title)[i]);
		ttl.append('\"');
	}
	ttl.append(")\n");
	char *str_ttl = ttl.to_string();

	std::vector<char*>* row = NULL;

	size_t count = 0;
	
	while (true) {
		OUTER_CONTINUE:
		sql.append(str_ttl);

		row = csv.read_row();
		if (row != NULL) {
			sql.append("SELECT ");
			sql.append('\'');
			sql.append((*row)[0]);
			sql.append('\'');
			for (int i = 1; i < row->size(); i++) {
				sql.append(",\'");
				sql.append((*row)[i]);
				sql.append('\'');
			}
			sql.append(" FROM DUAL\n");
			count += 1;
		}
		else {
			goto OUTER_BREAK;
		}

		delete row;
		row = csv.read_row();
		while (row != NULL) {
			sql.append("UNION ALL SELECT ");
			sql.append('\'');
			sql.append((*row)[0]);
			sql.append('\'');
			for (int i = 1; i < row->size(); i++) {
				sql.append(",\'");
				sql.append((*row)[i]);
				sql.append('\'');
			}
			sql.append(" FROM DUAL\n");
			count += 1;

			if (count % limit == 0) {
				sql.append(";\n\n");
				goto OUTER_CONTINUE;
			}

			delete row;
			row = csv.read_row();
		}
		break;
	}
	OUTER_BREAK:;

	fwrite(sql.to_string(), sql.size(), 1, output);

	fclose(output);
	return 0;
}
